package na.learn.java.combinatorics;

public class SingleThreadedPermutator extends AbstractPermutator {

	public StringBuffer generatePermutations(String source) {

		return permutate(source, 1);
	}

	public StringBuffer generateAllPermutations(String source) {
		StringBuffer buffer = new StringBuffer();
		int length = source.length();
		for(int count = 1; count <= length; count++)
			buffer.append("\n").append(	(source.substring(0,count)));
		return buffer;
	}

	public int countPermutations(String source) {
		return count(source, 1);
	}

	/**
	 * 1.  permutate(sourceString, level) : StringBuffer
	 * 		if level = length then return buffer.append(" ").append(sourceString);
	 * 
	 * 2. for count = level to length
	 * 		2a. permutate(swap(sourceString, level, count), level + 1)
	 * @param source
	 * @param level
	 * @return
	 */
	private StringBuffer permutate(String source, int level) {

		int length = source.length();
		StringBuffer buffer = new StringBuffer();

		if (level == length)
			return new StringBuffer().append(" ").append(source);

		for (int posCounter = level; posCounter <= length; posCounter++)
			buffer.append(permutate(swap(source, level, posCounter), level + 1));

		return buffer;

	}

	/**
	 * 1.  permutate(sourceString, level) : StringBuffer
	 * 		if level = length then return buffer.append(" ").append(sourceString);
	 * 
	 * 2. for count = level to length
	 * 		2a. permutate(swap(sourceString, level, count), level + 1)
	 * @param source
	 * @param level
	 * @return
	 */
	private int count(String source, int level) {
		int numPermutations = 0;
		int length = source.length();
		StringBuffer buffer = new StringBuffer();

		if (level == length)
			return 1;
		for (int posCounter = level; posCounter <= length; posCounter++)
			numPermutations += count(swap(source, level, posCounter), level + 1);
		return numPermutations;
	}

}
